//#include <iostream>
//using namespace std;
//
//
//class A 
//{
//public:
//	virtual void func() final
//	{
//		cout << "aaa" << endl;
//	}
//
//	int _a;
//};
//
//class B : public A
//{
//public:
//	virtual void func()
//	{
//		cout << "bbb" << endl;
//	}
//
//	int _b;
//};
//
//int main()
//{
//	return 0;
//}


//#include <iostream>
//using namespace std;
//
//const int N = 2e5 + 10;
//
//int a[N] = { 0 };
//int n, m;
//
//int get_m(int x)
//{
//    int ret = 0;
//    for (int i = 0; i < n; i++)
//    {
//        int l = a[i];
//        int r = a[i + 1];
//        if (r - l <= x)
//        {
//            continue;
//        }
//        else
//        {
//            while (r - l > x)
//            {
//                l += x;
//                ret++;
//            }
//        }
//    }
//
//    return ret;
//}
//
//int main()
//{
//    cin >> n >> m;
//    for (int i = 1; i <= n; i++)
//    {
//        cin >> a[i];
//    }
//
//    int left = 0;
//    int right = 1e9;
//    while (left < right)
//    {
//        int mid = (left + right) / 2;
//        if (get_m(mid) > m + 1)
//        {
//            left = mid + 1;
//        }
//        else
//        {
//            right = mid;
//        }
//    }
//
//    cout << left << endl;
//    return 0;
//}

//
//#include <iostream>
//#include <string>
//#include <algorithm>
//using namespace std;
//
//string a, b;
//int len1, len2;
//
//int main()
//{
//    cin >> len1 >> len2;
//    cin >> a >> b;
//    sort(b.begin(), b.end());
//
//    string ret;
//    int i = 0;
//    int j = 0;
//
//    while (i < len1 && j < len2)
//    {
//        if (a[i] <= b[j])
//        {
//            ret += a[i];
//            i++;
//        }
//        else
//        {
//            ret += b[j];
//            j++;
//        }
//    }
//
//    if (i == len1)
//    {
//        for (; j < len2; j++)
//        {
//            ret += b[j];
//        }
//    }
//
//    if (j == len2)
//    {
//        for (; i < len1; i++)
//        {
//            ret += a[i];
//        }
//    }
//
//    cout << ret << endl;
//    return 0;
//}


#include <iostream>
#include <algorithm>
#include <map>
using namespace std;

const int N = 110;

int dx[] = { 0, 0, 1, -1 };
int dy[] = { 1, -1, 0, 0 };

int a[N][N] = { 0 };
int f[N * N] = { 0 };

int n, m;

struct node
{
	int idx;
	int idy;
	int val;
};

bool cmp(node& a, node& b)
{
	return a.val < b.val;
}

node mp[N * N];

int main()
{
	cin >> n >> m;
	
	int cnt = 0;
	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= m; j++)
		{
			cin >> a[i][j];
			mp[++cnt].val = a[i][j];
			mp[cnt].idx = i;
			mp[cnt].idy = j;
		}
	}

	sort(mp + 1, mp + 1 + cnt, cmp);
	
	int ret = 0;

	for (int g = 1; g <= n * m; g++)
	{
		int i = mp[g].idx;
		int j = mp[g].idy;
		for (int k = 0; k < 4; k++)
		{
			int x = i + dx[k];
			int y = j + dy[k];
			if (x > 0 && x <= n && y > 0 && y <= m && a[x][y] <= a[i][j])
			{
				f[g] = max(f[g], f[a[x][y]] + 1);
				ret = max(ret, f[g]);
			}
		}
	}

	cout << ret + 1 << endl;

	return 0;
}